/*
 * @Author: 13177709051 3506463075@qq.com
 * @Date: 2024-11-23 11:19:26
 * @LastEditors: 13177709051 3506463075@qq.com
 * @LastEditTime: 2024-11-23 15:06:05
 * @FilePath: /linux35/Thread.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>

namespace ThreadMoudle
{
    // 线程要执行的方法，后面我们随时调整
    // typedef void (*func_t)(ThreadData *td); // 函数指针类型

    // typedef std::function<void()> func_t;
    using func_t = std::function<void(const std::string&)>;

    class Thread
    {
    public:
        void Excute()
        {
            _isrunning = true;
            _func(_name);
            _isrunning = false;
        }
    public:
        Thread(const std::string &name, func_t func):_name(name), _func(func)
        {
        }
        static void *ThreadRoutine(void *args) // 新线程都会执行该方法！
        {
            Thread *self = static_cast<Thread*>(args); // 获得了当前对象
            self->Excute();
            return nullptr;
        }
        bool Start()
        {
            int n = ::pthread_create(&_tid, nullptr, ThreadRoutine, this);
            if(n != 0) return false;
            return true;
        }
        std::string Status()
        {
            if(_isrunning) return "running";
            else return "sleep";
        }
        void Stop()
        {
            if(_isrunning)
            {
                ::pthread_cancel(_tid);
                _isrunning = false;
            }
        }
        void Join()
        {
            ::pthread_join(_tid, nullptr);
        }
        std::string Name()
        {
            return _name;
        }
        ~Thread()
        {
        }

    private:
        std::string _name;
        pthread_t _tid;
        bool _isrunning;
        func_t _func; // 线程要执行的回调函数
    };
} // namespace ThreadModle

// 线程函数类型 func_t
// using func_t = std::function<void(const std::string&)>;
// 这里使用了 std::function 来定义线程要执行的函数类型。func_t 是一个函数对象类型，它表示接受一个 std::string 类型参数并返回 void 的函数。使用 std::function 的好处是，它可以适配普通函数、lambda 表达式以及成员函数等，使得线程任务的定义更加灵活。
// Thread 类
// Thread 类是该代码的核心，封装了 POSIX 线程的管理操作，包括线程的创建、执行、停止、等待和状态查询。
// 成员变量
// _name: 线程的名称，用于标识线程。
// _tid: 线程标识符 (pthread_t 类型)，用于标识线程。
// _isrunning: 布尔变量，表示线程是否正在运行。
// _func: 线程执行的任务（即回调函数），使用 func_t 类型存储。
// 构造函数
// Thread 类的构造函数接收线程名称 (name) 和线程任务 (func) 作为参数，并初始化相关成员变量。_isrunning 被初始化为 false，表示线程在创建时默认处于非运行状态。
// 线程执行方法 Excute
// Excute 方法是线程执行的主体部分，它首先将 _isrunning 设置为 true，然后执行通过构造函数传入的任务函数 _func。执行完后，将 _isrunning 设置为 false，表示线程已经结束执行。
// 线程例程 ThreadRoutine
// ThreadRoutine 是一个静态方法，它会作为线程的入口函数。当创建线程时，系统会调用这个函数。
// 在 ThreadRoutine 中，首先通过 static_cast 将传入的 void* 类型的参数转换为 Thread* 类型，这样我们就可以访问到线程的成员变量和方法。
// 然后调用 self->Excute()，即执行线程实际的工作。
// 启动线程 Start
// Start 方法通过 pthread_create 创建一个新的线程。pthread_create 会接受线程标识符 _tid、线程属性（这里是 nullptr，即默认属性）、线程入口函数（这里是 ThreadRoutine）以及线程传递的参数（这里是 this，即当前对象）。
// 如果线程创建成功，返回 true；否则返回 false。
// 查询线程状态 Status
// Status 方法返回当前线程的状态。如果线程正在执行（_isrunning == true），返回 "running"，否则返回 "sleep"。
// 停止线程 Stop
// Stop 方法用于停止正在运行的线程。它调用 pthread_cancel 来请求终止指定线程 _tid。然后将 _isrunning 设置为 false，表示线程已停止。
// 等待线程完成 Join
// Join 方法用于等待线程执行完毕。它通过 pthread_join 阻塞当前线程，直到指定线程 _tid 执行完毕。
// 获取线程名称 Name
// Name 方法返回线程的名称。


// 1. 线程入口函数的要求
// 在使用 POSIX 线程库 (pthread) 创建线程时，pthread_create 函数要求线程的入口函数（也就是线程开始执行时调用的函数）必须是一个 静态函数 或 全局函数。这个函数的签名要求是：
// void *(*start_routine)(void *);
// 也就是说，start_routine 必须是一个接受 void* 参数并返回 void* 的函数指针。因此，不能直接使用非静态的成员函数作为线程的入口函数。
// 2. 成员函数与 this 指针
// 在 C++ 中，成员函数是绑定到特定对象实例上的。当我们调用一个成员函数时，隐式地会传入一个指向当前对象的 this 指针。对于普通的非静态成员函数，它的签名通常是：
// ReturnType ClassName::MemberFunction(Type1, Type2, ..., TypeN);
// 为了能够在成员函数中访问对象的成员变量和方法，编译器会自动将 this 指针传递给成员函数。这意味着在调用一个成员函数时，必须明确知道对象的实例。
// 3. 为什么 ThreadRoutine 必须是静态的
// 由于 pthread_create 要求线程入口函数是一个全局函数或静态成员函数，而静态成员函数没有 this 指针，因此它们不能访问对象的成员变量或非静态成员方法。然而，静态成员函数可以通过 显式地传递指针 来访问对象的成员变量。
// 在 Thread 类中，我们希望每个线程执行的函数是 Thread::Excute，这是一个非静态成员函数，能访问该对象的成员变量（如 _name, _func, _isrunning 等）。因此，为了能够在 ThreadRoutine 中调用 Excute 方法，我们必须将 ThreadRoutine 定义为静态成员函数。
// 4. ThreadRoutine 如何访问成员函数
// 在 ThreadRoutine 中，void *ThreadRoutine(void *args) 通过 static_cast<Thread*>(args) 将传入的 void* 类型的参数转换为 Thread* 类型，从而获取当前 Thread 对象的指针。通过该指针，我们就可以访问到对象的成员函数（如 Excute）。

// 由于线程入口函数的签名要求 void* (*start_routine)(void*)，而 ThreadRoutine 作为成员函数，通常会有一个 this 指针（即类实例的指针），这个 this 指针默认指向当前对象。
// 然而，成员函数不能直接用作 pthread_create 的入口函数，因为成员函数需要隐式地传递一个 this 指针来访问对象的成员，而 pthread_create 接受的是一个普通的函数指针，不能直接传递 this 指针。
// 为了解决这个问题，你使用了 static 修饰符，这样 ThreadRoutine 就变成了一个静态成员函数。静态成员函数 不 需要一个 this 指针来调用，可以直接作为普通函数来使用。

// 静态成员函数：不依赖于类的实例，调用时不需要 this 指针，因此可以作为普通函数传递给 pthread_create。它与类的实例无关，因此不需要访问类的成员变量或成员函数，除非通过其他手段（如通过参数传递类的实例指针）访问。
// 在你的代码中，static void* ThreadRoutine(void* args) 是一个静态成员函数，它作为线程的入口函数，在 pthread_create 中被调用时并不会隐式地传递 this 指针，但你可以通过参数 args 传递当前对象的指针（即 this）。
// 在 ThreadRoutine 中，你通过 static_cast<Thread*>(args) 将 args 转换为 Thread* 类型，然后访问类的成员（如 _name 和 _func），这就是你如何间接访问 Thread 对象的成员。


